package com.tongji.diy.model.furniturePlacementOptimization.accessibleBoundingBoxes
{
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Vector3D;

	public class FurnitureBasicBoundingBox
	{
		//private var _bondingBoxContorlPoints:Vector.<Vector3D>;
		//private static const basicBoxIndexcount:int = 0;
		
		private var _pairFurnitureIndex:int;//与该包围盒所对应的furniture的ID
		private var _location:Vector3D;
		private var _furnitureClass:int;
		private var _diagonal:Number;
		private var _distanceToNearestWall:Number;
		private var _angleWithNearestWall:Number;
		
		//以下是基本包围盒的控制变量
		private var _basicMinX:Number = Infinity;
		private var _basicMinY:Number = Infinity;
		private var _basicMaxX:Number = -Infinity;
		private var _basicMaxY:Number = -Infinity;
		//以下是accessible包围盒控制变量
		private var _accessMinX:Number = Infinity;
		private var _accessMinY:Number = Infinity;
		private var _accessMaxX:Number = -Infinity;
		private var _accessMaxY:Number = -Infinity;
		
		private var _width:Number;
		private var _length:Number;
		private var _height:Number;
		private var _angle:Number;//以欧拉角方式存储
		
		private var _basicBoundingBox2D:Vector.<Point>;
		
		private var _parentRoomIndex:int = -1;
		
		private var _spaceOrdinal:int = 1;
		
		private var _accessibleBoundingBox:Vector.<Point>;
		
		//private var _candidateOriented:Vector.<Number> = new Vector.<Number>;
		
		//角度采用弧度表示,实际中length以及location.y对应sence中的z轴，height以及location.z对应sence中的y轴
		public function FurnitureBasicBoundingBox(location:Vector3D, width:Number, length:Number, height:Number, angle:Number, parentRoomIndex:int, pairFurnitureIndex:int, furnitureClass:int)
		{
			_pairFurnitureIndex = pairFurnitureIndex;
			
			_width = width;
			_length = length;
			_height = height;
			_angle = angle;
			_location = location;
			_parentRoomIndex = parentRoomIndex;
			_furnitureClass = furnitureClass;
			
			_diagonal = Math.sqrt(_width*_width/4 + _length*_length/4);
			_basicBoundingBox2D = OBB2D(_location, _width, _length, _angle);
		/*	_minX = _location.x - width/2;
			_maxX = _location.x + width/2;
			_minY = _location.y - length/2;
			_maxY = _location.y + length/2;
			_minZ = _location.z - height/2;
			_maxZ = _location.z + height/2;*/
		}
		
		public function clone():FurnitureBasicBoundingBox
		{
			return new FurnitureBasicBoundingBox(_location,_width,_length,_height,_angle,_parentRoomIndex,_pairFurnitureIndex,_furnitureClass);
		}
		
		//设置备选合法的方向，该方向的计算过程在optimizationModel中caculatecandidateoriental函数提供
//		public function set candidateOriented(candidateOriented:Vector.<Number>):void
//		{
//			_candidateOriented = candidateOriented;
//		}
//		
//		public function get candidateOriented():Vector.<Number>
//		{
//			return _candidateOriented;
//		}
		
		public function get accessibleBoundingBox():Vector.<Point>
		{
			return _accessibleBoundingBox;
		}
		
		public function set accessibleBoundingBox(accessibleBoundingBox:Vector.<Point>):void
		{
			this._accessibleBoundingBox = accessibleBoundingBox;
		}
		
		public function get distanceToNearestWall():Number
		{
			return _distanceToNearestWall;
		}
		
		public function get angleWithNearestWall():Number
		{
			return _angleWithNearestWall;
		}
		//distanceToNearestWall的值并不是从该类中进行计算得到的，其值是在furnitureOptimization中对应的toNearestWallDistanceAndAngle函数实时进行计算的
		public function set distanceToNearestWall(distanceToNearestWall:Number):void
		{
			_distanceToNearestWall = distanceToNearestWall;
		}
		//angleWithNearestWall的值并不是从该类中进行计算得到的，其值是在furnitureOptimization中对应的toNearestWallDistanceAndAngle函数实时进行计算的
		public function set angleWithNearestWall(angleWithNearestWall:Number):void
		{
			_angleWithNearestWall = angleWithNearestWall;
		}
		
		
		public function get angle():Number
		{
			return _angle;
		}
		
		public function get width():Number
		{
			return _width;
		}
		
		public function get length():Number
		{
			return _length;
		}
		
		public function get height():Number
		{
			return _height;
		}
		
		public function get diagonal():Number
		{
			return _diagonal;
		}
		
		public function get pairFurnitureIndex():int
		{
			return _pairFurnitureIndex;
		}
		
		public function get spaceOrdinal():int
		{
			return _spaceOrdinal;
		}
		
		public function set furnitureClass(furnitureClass:int):void
		{
			_furnitureClass = furnitureClass;
		}
		
		public function set spaceOrdinal(spaceOrdinal:int):void
		{
			_spaceOrdinal = spaceOrdinal;
		}
		
		public function get furnitureClass():int
		{
			return _furnitureClass;
		}
		
		public function get basicBoundingBox2D():Vector.<Point>
		{
			return _basicBoundingBox2D;
		}
		
		//角度使用弧度 ,返回值是相对于房间的坐标的OBB；同时更新maxX,maxY,minX,minY
		private function OBB2D(location:Vector3D, width:Number, length:Number, angle:Number):Vector.<Point>
		{
			var AABB:Vector.<Point> = new Vector.<Point>;
			var leftTop:Point = new Point(location.x - width/2, location.y + length/2);
			AABB.push(leftTop);
			var rightTop:Point = new Point(location.x + width/2, location.y + length/2);
			AABB.push(rightTop);
			var rightBottom:Point = new Point(location.x + width/2, location.y - length/2);
			AABB.push(rightBottom);
			var leftBottom:Point = new Point(location.x - width/2, location.y - length/2);
			AABB.push(leftBottom);
			
			var moveM1:Matrix = new Matrix();
			moveM1.translate(-location.x, -location.y);
			var moveM2:Matrix = new Matrix();
			moveM2.translate(location.x, location.y);
			var rotateM:Matrix = new Matrix();
			rotateM.rotate(-angle);
			moveM1.concat(rotateM);
			moveM1.concat(moveM2);
			var transM:Matrix = moveM1;
			
			_basicMaxX = -Infinity;
			_basicMaxY = -Infinity;
			_basicMinX = Infinity;
			_basicMinY = Infinity;
			
			for(var i:int = 0;i<AABB.length;i++)
			{
				AABB[i] = transM.transformPoint(AABB[i]);
				if(_basicMaxX < AABB[i].x)
					_basicMaxX = AABB[i].x;
				if(_basicMinX > AABB[i].x)
					_basicMinX = AABB[i].x;
				if(_basicMaxY < AABB[i].y)
					_basicMaxY = AABB[i].y;
				if(_basicMinY > AABB[i].y)
					_basicMinY = AABB[i].y;
			}
			
			return AABB;
			
		}
		//角度以弧度方式存储
		public function set angle(angle:Number):void
		{
			_angle = angle;
			_basicBoundingBox2D = OBB2D(this.location, this.width, this.length, this.angle);
		}
		
		public function set location(location:Vector3D):void
		{
			_location = location;
			_basicBoundingBox2D = OBB2D(this.location, this.width, this.length, this.angle);
			/*_minX = _location.x - width/2;
			_maxX = _location.x + width/2;
			_minY = _location.y - length/2;
			_maxY = _location.y + length/2;
			_minZ = _location.z - height/2;
			_maxZ = _location.z + height/2;*/
		}
		
		public function get location():Vector3D
		{
			return _location;
		}
		
		public function set parentRoomIndex(parentRoomIndex:int):void
		{
			_parentRoomIndex = parentRoomIndex;
		}
		
		public function get parentRoomIndex():int
		{
			return _parentRoomIndex;
		}
		
		public function set basicMinX(minX:Number):void
		{
			_basicMinX = minX;
		}
		
		public function set basicMinY(minY:Number):void
		{
			_basicMinY = minY;
		}
		
		
		public function set basicMaxX(maxX:Number):void
		{
			_basicMaxX = maxX;
		}
		
		public function set basicMaxY(maxY:Number):void
		{
			_basicMaxY = maxY;
		}
		
		public function get basicMinX():Number
		{
			return _basicMinX;
		}
		
		public function get basicMinY():Number
		{
			return _basicMinY;
		}
	
		public function get basicMaxX():Number
		{
			return _basicMaxX;
		}
		
		public function get basicMaxY():Number
		{
			return _basicMaxY;
		}
		
		public function set accessMinX(minX:Number):void
		{
			_accessMinX = minX;
		}
		
		public function set accessMinY(minY:Number):void
		{
			_accessMinY = minY;
		}
		
		
		public function set accessMaxX(maxX:Number):void
		{
			_accessMaxX = maxX;
		}
		
		public function set accessMaxY(maxY:Number):void
		{
			_accessMaxY = maxY;
		}
		
		public function get accessMinX():Number
		{
			return _accessMinX;
		}
		
		public function get accessMinY():Number
		{
			return _accessMinY;
		}
		
		
		public function get accessMaxX():Number
		{
			return _accessMaxX;
		}
		
		public function get accessMaxY():Number
		{
			return _accessMaxY;
		}
	}
}